Head First 设计模式

策略模式

定义

定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

UML

思路

设计原则:抽取可能发生改变的,与不会发生改变的隔离。

将会发生改变的相关性强的行为或者功能抽象,抽取,定义为一个接口:

1
2
3
4
5
interface IStrategy{

public void Func();

}

定义该接口下不同的方法:

方法A:

1
2
3
4
5
6
7
8
9
class ConcreteStrategyA implements IStrategy{

public void Func(){

System.out.println("ConcreteStrategyA类,FuncA().");

}

}

方法B:

1
2
3
4
5
6
7
8
9
class ConcreteStrategyB implements IStrategy{

public void Func(){

System.out.println("ConcreteStrategyB类,FuncB().");

}

}

方法C:

1
2
3
4
5
6
7
8
9
class ConcreteStrategyC implements IStrategy{

public void Func(){

System.out.println("ConcreteStrategyC类,FuncC().");

}

}

使用该功能的类持有该接口的引用:

1
2
3
4
5
6
7
8
9
10
public class Strategy{

public static void main(String args[]){

IStrategy iStrategy = new ConcreteStrategyA();
iStrategy.Func();

}

}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Strategy{

public static void main(String args[]){

IStrategy iStrategy = new ConcreteStrategyA();
iStrategy.Func();
iStrategy = new ConcreteStrategyB();
iStrategy.Func();
iStrategy = new ConcreteStrategyC();
iStrategy.Func();

}

}

编译运行:

是的,非常简单,你会发现其实就是多态的体现。

当然这里举的只是最基本的例子,实际开发会在该基础上复杂化,但是基本框架是不变的。

观察者模式

定义

定义了对象之间的一对多依赖。当一个对象改变,它的依赖者都会收到通知并做出改变。

UML

思路

设计原则:为了交互对象之间的松耦合设计而努力。

定义一个主题接口,定义注册订阅者移除订阅者,以及通知订阅者方法:

1
2
3
4
5
6
7
interface Subject{

public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();

}

定义一个订阅者接口,定义一个更新方法:

1
2
3
4
5
interface Observer{

public void update(String str);

}

定义一个主题类,实现主题接口中的方法。

维护一个订阅者列表,注册时加入列表,取消时移出列表,内容更新就遍历列表逐个通知。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class ConcreteSubject implements Subject{

private List<Observer> observers;
private String updateStr;

public ConcreteSubject(){

observers = new ArrayList<Observer>();

}

public void registerObserver(Observer o){

observers.add(o);

}

public void removeObserver(Observer o){

if(observers.indexOf(o)>=0){
observers.remove(observers.indexOf(o));
}

}

public void notifyObservers(){

for (int i=0; i<observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(updateStr);
}

}

public void setUpdateStr(String updateStr){

this.updateStr = updateStr;
updateStrChanged();

}

public void updateStrChanged(){

notifyObservers();

}

}

定义一个观察者类,实现观察者接口中的所有方法,通过主题实现类的引用订阅主题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ConcreteObserver implements Observer{

private String updateStr;
private Subject mConcreteSubject;

public ConcreteObserver(Subject concreteSubject){

this.mConcreteSubject = concreteSubject;
mConcreteSubject.registerObserver(this);

}

public void update(String str){

System.out.println(str);

}

}

测试

创建主题和订阅者对象,修改主题内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestClass{

public static void main(String[] args) {

ConcreteSubject concreteSubject = new ConcreteSubject();
Observer concreteObserver = new ConcreteObserver(concreteSubject);
concreteSubject.setUpdateStr("主题改变A");
concreteSubject.setUpdateStr("主题改变B");
concreteSubject.setUpdateStr("主题改变C");

}

}

编译运行:

其实 Java 中就有内置观察者模式,不过与上面结构有一点区别。

其中 Observer 还是接口形式,Subject 接口变成了 Observable 抽象类。许多功能都已经实现好了,直接使用 Observable 的 addObserver()deleteObserver() 就可以添加以及取消订阅了。

并且在 update() 方法中,需要传入两个参数,一个主题,一个订阅者,用于更新来自不同主题的内容,更加灵活。

不过总体的结构和思想是一样的。

装饰者模式

定义

动态地将责任附加到对象上,装饰者提供了比继承更有弹性的扩展功能。

UML

思路

设计原则:类应该对扩展开放,对修改关闭。

定义一个基类:

1
2
3
4
5
6
7
8
9
10
11
abstract class Component{

String description = "Component";

public String methodA(){
return description;
}

public abstract void methodB();

}

为了方便测试,其中一个方法将显示该类名。

接着定义一个或者多个组件,继承基类:

1
2
3
4
5
6
7
8
9
10
11
class ConcreteComponent extends Component{
String description = "ConcreteComponent";

public ConcreteComponent(){
description = "ConcreteComponent";
}

public void methodB(){

}
}

定义一个装饰者抽象类,这样之前定义的组件和它就是同一类型了:

1
2
3
4
5
6
7
abstract class Decorator extends Component{

public abstract String methodA();

public abstract void methodB();

}

继承装饰者抽象类,根据不同需求,定义各自的装饰内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ConcreteDecoratorA extends Decorator{
Component component;

public ConcreteDecoratorA(Component component){
this.component = component;
}

public String methodA(){
return component.methodA() + ",ConcreteDecoratorA";
}

public void methodB(){

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ConcreteDecoratorB extends Decorator{

Component component;

public ConcreteDecoratorB(Component component){
this.component = component;
}

public String methodA(){
return component.methodA() + ",ConcreteDecoratorB";
}

public void methodB(){

}
}

测试

因为就一个组件,可能测试效果不是很好,但是也可以看得出来用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestClass1{

public static void main(String[] args) {

Component component1 = new ConcreteComponent();
component1 = new ConcreteDecoratorA(component1);
component1 = new ConcreteDecoratorB(component1);
component1 = new ConcreteDecoratorA(component1);
System.out.println(component1.methodA());

Component component2 = new ConcreteComponent();
component2 = new ConcreteDecoratorB(component2);
component2 = new ConcreteDecoratorA(component2);
System.out.println(component2.methodA());

}

}

编译运行

可以看得出来,该结构非常的灵活。(对象的建立不大优雅,之后会有更好的模式可以运用)

画图工具使用 Chrome 应用 Gliffy Diagrams ,好用看得见。